﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VTR.Core
{
    /// <summary>
	/// This class provides the logic for checking the validity
	/// of a 17-digit VIN number
	/// according to e.g. http://www.vehicleidentificationnumber.com/vehicle_identification_numbers_vin_detail.html
	/// </summary>
    public class VINEdits
    {
        public static bool CheckVINValid(string vin)
        {
            string strVin = vin.Trim();
            if (strVin.Length != 17) return false;
            int sum = 0;
            for (int i = 1; i <= strVin.Length; i++)
            {
                int val = 0;
                int weight = 0;
                if (i != 9)
                {
                    char p = strVin[i - 1];
                    try
                    {
                        val = GetNumber(p);
                        weight = GetWeight(i);
                    }
                    catch
                    {
                        return false;
                    }
                    sum += (val * weight);
                }
            }
            char checkDigit;
            int remainder = sum % 11;
            if (remainder == 10)
            {
                checkDigit = 'X';
            }
            else
            {
                checkDigit = remainder.ToString()[0];
            }
            char origCheckDigit = strVin[8];
            return checkDigit.Equals(origCheckDigit);
        }

        private static int GetNumber(char p)
        {
            int val = 0;
            switch (p)
            {
                case '0':
                    val = 0;
                    break;
                case '1':
                case 'A':
                case 'J':
                    val = 1;
                    break;
                case '2':
                case 'B':
                case 'K':
                case 'S':
                    val = 2;
                    break;
                case '3':
                case 'C':
                case 'L':
                case 'T':
                    val = 3;
                    break;
                case '4':
                case 'D':
                case 'M':
                case 'U':
                    val = 4;
                    break;
                case '5':
                case 'E':
                case 'N':
                case 'V':
                    val = 5;
                    break;
                case '6':
                case 'F':
                case 'W':
                    val = 6;
                    break;
                case '7':
                case 'G':
                case 'P':
                case 'X':
                    val = 7;
                    break;
                case '8':
                case 'H':
                case 'Y':
                    val = 8;
                    break;
                case '9':
                case 'R':
                case 'Z':
                    val = 9;
                    break;
                default:
                    throw new Exception("VinChecker.GetNumber: Invalid digit encountered: " + p);
            }
            return val;
        }

        private static int GetWeight(int index)
        {
            switch (index)
            {
                case 1:
                case 11:
                    return 8;
                case 2:
                case 12:
                    return 7;
                case 3:
                case 13:
                    return 6;
                case 4:
                case 14:
                    return 5;
                case 5:
                case 15:
                    return 4;
                case 6:
                case 16:
                    return 3;
                case 7:
                case 17:
                    return 2;
                case 8:
                    return 10;
                case 10:
                    return 9;
                default:
                    throw new Exception("VinChecker.GetWeight: Invalid index encountered: " + index);
            }
        }

    }
}
